<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>面试必问 | 聊聊MyBatis执行流程？ | 冰河技术</title>
    <meta name="generator" content="VuePress 1.9.7">
    <link rel="icon" href="/favicon.ico">
    <script charset="utf-8" async="async" src="/js/jquery.min.js"></script>
    <script charset="utf-8" async="async" src="/js/global.js"></script>
    <script charset="utf-8" async="async" src="/js/fingerprint2.min.js"></script>
    <script charset="utf-8" async="async" src="https://v1.cnzz.com/z_stat.php?id=1281063564&amp;web_id=1281063564"></script>
    <script charset="utf-8" async="async" src="https://s9.cnzz.com/z_stat.php?id=1281064551&amp;web_id=1281064551"></script>
    <script>
            var _hmt = _hmt || [];
            (function() {
              var hm = document.createElement("script");
              hm.src = "https://hm.baidu.com/hm.js?d091d2fd0231588b1d0f9231e24e3f5e";
              var s = document.getElementsByTagName("script")[0];
              s.parentNode.insertBefore(hm, s);
            })();
            </script>
    <meta name="description" content="包含：编程语言，开发技术，分布式，微服务，高并发，高可用，高可扩展，高可维护，JVM技术，MySQL，分布式数据库，分布式事务，云原生，大数据，云计算，渗透技术，各种面试题，面试技巧...">
    <meta property="article:modified_time" content="2022-05-23T11:30:51.000Z">
    <meta property="og:title" content="面试必问 | 聊聊MyBatis执行流程？">
    <meta property="og:type" content="article">
    <meta property="og:url" content="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html">
    <meta name="twitter:title" content="面试必问 | 聊聊MyBatis执行流程？">
    <meta name="twitter:url" content="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="robots" content="all">
    <meta name="author" content="冰河">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <meta name="keywords" content="冰河，冰河技术, 编程语言，开发技术，分布式，微服务，高并发，高可用，高可扩展，高可维护，JVM技术，MySQL，分布式数据库，分布式事务，云原生，大数据，云计算，渗透技术，各种面试题，面试技巧">
    <meta name="apple-mobile-web-app-capable" content="yes">
    
    <link rel="preload" href="/assets/css/0.styles.ab888ebb.css" as="style"><link rel="preload" href="/assets/css/styles.css?v=1653305936337" as="style"><link rel="preload" href="/assets/js/cg-styles.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-app.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-4.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-3.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-276.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-5.js?v=1653305936337" as="script"><link rel="preload" href="/assets/js/cg-6.js?v=1653305936337" as="script">
    <link rel="stylesheet" href="/assets/css/0.styles.ab888ebb.css"><link rel="stylesheet" href="/assets/css/styles.css?v=1653305936337">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">冰河技术</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/md/other/guide-to-reading.html" class="nav-link">
  导读
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="核心技术" class="dropdown-title"><span class="title">核心技术</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Java核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/java/basics/2022-04-28-全网最全正则表达式总结.html" class="nav-link">
  Java基础
</a></li><li class="dropdown-subitem"><a href="/md/core/java/advanced/default.html" class="nav-link">
  Java进阶
</a></li><li class="dropdown-subitem"><a href="/md/core/java/senior/default.html" class="nav-link">
  Java高级
</a></li><li class="dropdown-subitem"><a href="/md/core/java/java8/2022-03-31-001-Java8有哪些新特性呢？.html" class="nav-link">
  Java8新特性
</a></li></ul></li><li class="dropdown-item"><h4>
          Spring核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/spring/ioc/2022-04-04-001-聊聊Spring注解驱动开发那些事儿.html" class="nav-link">
  IOC核心技术
</a></li><li class="dropdown-subitem"><a href="/md/core/spring/aop/default.html" class="nav-link">
  AOP核心技术
</a></li></ul></li><li class="dropdown-item"><h4>
          JVM核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/jvm/2022-04-18-001-JVM调优的几种场景.html" class="nav-link">
  JVM调优技术
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="性能调优" class="dropdown-title"><span class="title">性能调优</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/performance/jvm/default.html" class="nav-link">
  JVM性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/tomcat/default.html" class="nav-link">
  Tomcat性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/mysql/default.html" class="nav-link">
  MySQL性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/system/default.html" class="nav-link">
  操作系统性能调优
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="并发编程" class="dropdown-title"><span class="title">并发编程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/concurrent/bottom/default.html" class="nav-link">
  底层技术
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/source/2020-03-30-001-一文搞懂线程与多线程.html" class="nav-link">
  源码分析
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/basics/2020-03-30-001-明明中断了线程，却为何不起作用呢？.html" class="nav-link">
  基础案例
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/ActualCombat/default.html" class="nav-link">
  实战案例
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/interview/default.html" class="nav-link">
  面试
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/framework/default.html" class="nav-link">
  系统架构
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="框架源码" class="dropdown-title"><span class="title">框架源码</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/frame/spring/default.html" class="nav-link">
  Spring源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/springmvc/default.html" class="nav-link">
  SpringMVC源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/mybatis/default.html" class="nav-link">
  MyBatis源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/dubbo/default.html" class="nav-link">
  Dubbo源码
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="分布式" class="dropdown-title"><span class="title">分布式</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          缓存技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/cache/default.html" class="nav-link">
  Redis
</a></li></ul></li><li class="dropdown-item"><h4>
          服务注册发现
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/zookeeper/default.html" class="nav-link">
  Zookeeper
</a></li></ul></li><li class="dropdown-item"><h4>
          消息中间件
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/mq/rabbitmq/default.html" class="nav-link">
  RabbitMQ
</a></li><li class="dropdown-subitem"><a href="/md/distributed/mq/rocketmq/default.html" class="nav-link">
  RocketMQ
</a></li><li class="dropdown-subitem"><a href="/md/distributed/mq/kafka/default.html" class="nav-link">
  Kafka
</a></li></ul></li><li class="dropdown-item"><h4>
          网络通信
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/netty/default.html" class="nav-link">
  Netty
</a></li></ul></li><li class="dropdown-item"><h4>
          远程调用
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/dubbo/default.html" class="nav-link">
  Dubbo
</a></li></ul></li><li class="dropdown-item"><h4>
          数据库
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/mongodb/default.html" class="nav-link">
  MongoDB
</a></li></ul></li><li class="dropdown-item"><h4>
          搜索引擎
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/es/default.html" class="nav-link">
  ElasticSearch
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="微服务" class="dropdown-title"><span class="title">微服务</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/microservices/springboot/default.html" class="nav-link">
  SpringBoot
</a></li><li class="dropdown-item"><!----> <a href="/md/microservices/springcloudalibaba/2022-04-02-SpringCloudAlibaba专栏开篇.html" class="nav-link">
  SpringCloudAlibaba
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="中间件" class="dropdown-title"><span class="title">中间件</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/middleware/bytecode/2022-04-11-001-工作多年的你依然重复做着CRUD-是否接触过这种技术.html" class="nav-link">
  字节码编程
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/threadpool/default.html" class="nav-link">
  手写线程池
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/limiter/default.html" class="nav-link">
  分布式限流
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/independent/default.html" class="nav-link">
  开源项目
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="项目实战" class="dropdown-title"><span class="title">项目实战</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/microservices/springcloudalibaba/2022-04-02-SpringCloudAlibaba专栏开篇.html" class="nav-link">
  SpringCloud Alibaba实战
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="渗透技术" class="dropdown-title"><span class="title">渗透技术</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/hack/environment/2022-04-17-001-安装Kali系统.html" class="nav-link">
  基础环境篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/tools/2022-04-17-001-使用Easy-Creds工具攻击无线网络.html" class="nav-link">
  渗透工具篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/horse/2022-05-02-001-各种一句话木马大全.html" class="nav-link">
  木马篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/sql/2022-05-02-001-sqli-labs-master下载与安装.html" class="nav-link">
  SQL注入篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/shell/2022-05-02-001-各种解析漏洞拿shell.html" class="nav-link">
  漏洞拿Shell篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/crack/2022-05-02-001-使用rarcrack暴力破解RAR-ZIP-7Z压缩包.html" class="nav-link">
  暴力破解篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/bash/2022-05-02-001-3389脚本开启代码(vbs版).html" class="nav-link">
  渗透脚本篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/raising/2022-05-02-001-数据库提权.html" class="nav-link">
  数据与系统提权篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/client/2022-05-02-001-浏览器渗透.html" class="nav-link">
  客户端渗透篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/sociology/2022-05-02-001-Metasploit之社会工程学工具包.html" class="nav-link">
  社会工程学
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/question/2022-05-02-001-HTTP错误4031禁止访问-执行访问被拒绝.html" class="nav-link">
  问题记录篇
</a></li></ul></div></div><div class="nav-item"><a href="/md/interview/2022-04-18-001-面试必问-聊聊JVM性能调优.html" class="nav-link">
  面试必问系列
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="📚PDF" class="dropdown-title"><span class="title">📚PDF</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          出版图书
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-深入理解分布式事务.html" class="nav-link">
  《深入理解分布式事务：原理与实战》
</a></li><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-MySQL技术大全.html" class="nav-link">
  《MySQL技术大全：开发、优化与运维实战》
</a></li><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-海量数据处理与大数据技术实战.html" class="nav-link">
  《海量数据处理与大数据技术实战》
</a></li></ul></li><li class="dropdown-item"><h4>
          电子书籍
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/knowledge/pdf/2022-03-30-《冰河的渗透实战笔记》电子书，442页，37万字，正式发布.html" class="nav-link">
  冰河的渗透实战笔记
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/about/me/about-me.html" class="nav-link">
  关于自己
</a></li><li class="dropdown-item"><!----> <a href="/md/about/study/default.html" class="nav-link">
  关于学习
</a></li><li class="dropdown-item"><!----> <a href="/md/about/job/default.html" class="nav-link">
  关于职场
</a></li></ul></div></div><div class="nav-item"><a href="https://space.bilibili.com/517638832" target="_blank" rel="noopener noreferrer" class="nav-link external">
  B站
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/binghe001/BingheGuide" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/md/other/guide-to-reading.html" class="nav-link">
  导读
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="核心技术" class="dropdown-title"><span class="title">核心技术</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Java核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/java/basics/2022-04-28-全网最全正则表达式总结.html" class="nav-link">
  Java基础
</a></li><li class="dropdown-subitem"><a href="/md/core/java/advanced/default.html" class="nav-link">
  Java进阶
</a></li><li class="dropdown-subitem"><a href="/md/core/java/senior/default.html" class="nav-link">
  Java高级
</a></li><li class="dropdown-subitem"><a href="/md/core/java/java8/2022-03-31-001-Java8有哪些新特性呢？.html" class="nav-link">
  Java8新特性
</a></li></ul></li><li class="dropdown-item"><h4>
          Spring核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/spring/ioc/2022-04-04-001-聊聊Spring注解驱动开发那些事儿.html" class="nav-link">
  IOC核心技术
</a></li><li class="dropdown-subitem"><a href="/md/core/spring/aop/default.html" class="nav-link">
  AOP核心技术
</a></li></ul></li><li class="dropdown-item"><h4>
          JVM核心技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/core/jvm/2022-04-18-001-JVM调优的几种场景.html" class="nav-link">
  JVM调优技术
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="性能调优" class="dropdown-title"><span class="title">性能调优</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/performance/jvm/default.html" class="nav-link">
  JVM性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/tomcat/default.html" class="nav-link">
  Tomcat性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/mysql/default.html" class="nav-link">
  MySQL性能调优
</a></li><li class="dropdown-item"><!----> <a href="/md/performance/system/default.html" class="nav-link">
  操作系统性能调优
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="并发编程" class="dropdown-title"><span class="title">并发编程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/concurrent/bottom/default.html" class="nav-link">
  底层技术
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/source/2020-03-30-001-一文搞懂线程与多线程.html" class="nav-link">
  源码分析
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/basics/2020-03-30-001-明明中断了线程，却为何不起作用呢？.html" class="nav-link">
  基础案例
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/ActualCombat/default.html" class="nav-link">
  实战案例
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/interview/default.html" class="nav-link">
  面试
</a></li><li class="dropdown-item"><!----> <a href="/md/concurrent/framework/default.html" class="nav-link">
  系统架构
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="框架源码" class="dropdown-title"><span class="title">框架源码</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/frame/spring/default.html" class="nav-link">
  Spring源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/springmvc/default.html" class="nav-link">
  SpringMVC源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/mybatis/default.html" class="nav-link">
  MyBatis源码
</a></li><li class="dropdown-item"><!----> <a href="/md/frame/dubbo/default.html" class="nav-link">
  Dubbo源码
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="分布式" class="dropdown-title"><span class="title">分布式</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          缓存技术
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/cache/default.html" class="nav-link">
  Redis
</a></li></ul></li><li class="dropdown-item"><h4>
          服务注册发现
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/zookeeper/default.html" class="nav-link">
  Zookeeper
</a></li></ul></li><li class="dropdown-item"><h4>
          消息中间件
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/mq/rabbitmq/default.html" class="nav-link">
  RabbitMQ
</a></li><li class="dropdown-subitem"><a href="/md/distributed/mq/rocketmq/default.html" class="nav-link">
  RocketMQ
</a></li><li class="dropdown-subitem"><a href="/md/distributed/mq/kafka/default.html" class="nav-link">
  Kafka
</a></li></ul></li><li class="dropdown-item"><h4>
          网络通信
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/netty/default.html" class="nav-link">
  Netty
</a></li></ul></li><li class="dropdown-item"><h4>
          远程调用
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/dubbo/default.html" class="nav-link">
  Dubbo
</a></li></ul></li><li class="dropdown-item"><h4>
          数据库
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/mongodb/default.html" class="nav-link">
  MongoDB
</a></li></ul></li><li class="dropdown-item"><h4>
          搜索引擎
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/distributed/es/default.html" class="nav-link">
  ElasticSearch
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="微服务" class="dropdown-title"><span class="title">微服务</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/microservices/springboot/default.html" class="nav-link">
  SpringBoot
</a></li><li class="dropdown-item"><!----> <a href="/md/microservices/springcloudalibaba/2022-04-02-SpringCloudAlibaba专栏开篇.html" class="nav-link">
  SpringCloudAlibaba
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="中间件" class="dropdown-title"><span class="title">中间件</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/middleware/bytecode/2022-04-11-001-工作多年的你依然重复做着CRUD-是否接触过这种技术.html" class="nav-link">
  字节码编程
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/threadpool/default.html" class="nav-link">
  手写线程池
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/limiter/default.html" class="nav-link">
  分布式限流
</a></li><li class="dropdown-item"><!----> <a href="/md/middleware/independent/default.html" class="nav-link">
  开源项目
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="项目实战" class="dropdown-title"><span class="title">项目实战</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/microservices/springcloudalibaba/2022-04-02-SpringCloudAlibaba专栏开篇.html" class="nav-link">
  SpringCloud Alibaba实战
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="渗透技术" class="dropdown-title"><span class="title">渗透技术</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/hack/environment/2022-04-17-001-安装Kali系统.html" class="nav-link">
  基础环境篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/tools/2022-04-17-001-使用Easy-Creds工具攻击无线网络.html" class="nav-link">
  渗透工具篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/horse/2022-05-02-001-各种一句话木马大全.html" class="nav-link">
  木马篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/sql/2022-05-02-001-sqli-labs-master下载与安装.html" class="nav-link">
  SQL注入篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/shell/2022-05-02-001-各种解析漏洞拿shell.html" class="nav-link">
  漏洞拿Shell篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/crack/2022-05-02-001-使用rarcrack暴力破解RAR-ZIP-7Z压缩包.html" class="nav-link">
  暴力破解篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/bash/2022-05-02-001-3389脚本开启代码(vbs版).html" class="nav-link">
  渗透脚本篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/raising/2022-05-02-001-数据库提权.html" class="nav-link">
  数据与系统提权篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/client/2022-05-02-001-浏览器渗透.html" class="nav-link">
  客户端渗透篇
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/sociology/2022-05-02-001-Metasploit之社会工程学工具包.html" class="nav-link">
  社会工程学
</a></li><li class="dropdown-item"><!----> <a href="/md/hack/question/2022-05-02-001-HTTP错误4031禁止访问-执行访问被拒绝.html" class="nav-link">
  问题记录篇
</a></li></ul></div></div><div class="nav-item"><a href="/md/interview/2022-04-18-001-面试必问-聊聊JVM性能调优.html" class="nav-link">
  面试必问系列
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="📚PDF" class="dropdown-title"><span class="title">📚PDF</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          出版图书
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-深入理解分布式事务.html" class="nav-link">
  《深入理解分布式事务：原理与实战》
</a></li><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-MySQL技术大全.html" class="nav-link">
  《MySQL技术大全：开发、优化与运维实战》
</a></li><li class="dropdown-subitem"><a href="/md/knowledge/book/2022-03-29-海量数据处理与大数据技术实战.html" class="nav-link">
  《海量数据处理与大数据技术实战》
</a></li></ul></li><li class="dropdown-item"><h4>
          电子书籍
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/md/knowledge/pdf/2022-03-30-《冰河的渗透实战笔记》电子书，442页，37万字，正式发布.html" class="nav-link">
  冰河的渗透实战笔记
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/about/me/about-me.html" class="nav-link">
  关于自己
</a></li><li class="dropdown-item"><!----> <a href="/md/about/study/default.html" class="nav-link">
  关于学习
</a></li><li class="dropdown-item"><!----> <a href="/md/about/job/default.html" class="nav-link">
  关于职场
</a></li></ul></div></div><div class="nav-item"><a href="https://space.bilibili.com/517638832" target="_blank" rel="noopener noreferrer" class="nav-link external">
  B站
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://github.com/binghe001/BingheGuide" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>面试必问系列</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/md/interview/2022-04-18-001-面试必问-聊聊JVM性能调优.html" class="sidebar-link">面试必问 | 聊聊JVM性能调优？</a></li><li><a href="/md/interview/2022-04-18-002-面试必问-聊聊MyBatis执行流程.html" class="active sidebar-link">面试必问 | 聊聊MyBatis执行流程？</a></li><li><a href="/md/interview/2022-05-06-面试必问-哪些场景下Spring的事务会失效.html" class="sidebar-link">面试必问 | 哪些场景下Spring的事务会失效？</a></li><li><a href="/md/interview/2022-05-06-面试必问-如何设计一款高并发的消息中间件.html" class="sidebar-link">面试必问 | 如何设计一款高并发的消息中间件？</a></li><li><a href="/md/interview/2022-05-09-面试必问-聊聊MySQL三大核心日志的实现原理.html" class="sidebar-link">面试必问 | 聊聊MySQL三大核心日志的实现原理？</a></li><li><a href="/md/interview/2022-05-16-面试必问-聊聊Kafka的消费模型.html" class="sidebar-link">面试必问 | 聊聊Kafka的消费模型？</a></li></ul></section></li></ul> </aside> <div><main class="page"> <div class="theme-default-content content__default"><h1 id="面试必问-聊聊mybatis执行流程"><a href="#面试必问-聊聊mybatis执行流程" class="header-anchor">#</a> 面试必问 | 聊聊MyBatis执行流程？</h1> <p><strong>大家好，我是冰河~~</strong></p> <p>随着互联网的发展，越来越多的公司摒弃了Hibernate，而选择拥抱了MyBatis。而且，很多大厂在面试的时候喜欢问MyBatis底层的原理和源码实现。</p> <p>总之，MyBatis几乎成为了Java开发人员必须深入掌握的框架技术，今天，我们就一起来深入分析MyBatis源码。文章有点长，建议先收藏后慢慢研究。整体三万字左右，全程高能，小伙伴们可慢慢研究。</p> <p>本文主要结构如下所示。</p> <p><img alt="" data-src="https://img-blog.csdnimg.cn/img_convert/3b7ead336c53f4ca1d3b6070761bcd43.png" loading="lazy" class="lazy"></p> <h2 id="mybatis源码解析"><a href="#mybatis源码解析" class="header-anchor">#</a> MyBatis源码解析</h2> <p>大家应该都知道Mybatis源码也是对Jbdc的再一次封装,不管怎么进行包装,还是会有获取链接、preparedStatement、封装参数、执行这些步骤的。</p> <h2 id="配置解析过程"><a href="#配置解析过程" class="header-anchor">#</a> 配置解析过程</h2> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">String</span> resource <span class="token operator">=</span> <span class="token string">&quot;mybatis-config.xml&quot;</span><span class="token punctuation">;</span>
<span class="token comment">//1.读取resources下面的mybatis-config.xml文件</span>
<span class="token class-name">InputStream</span> inputStream <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//2.使用SqlSessionFactoryBuilder创建SqlSessionFactory</span>
<span class="token class-name">SqlSessionFactory</span> sqlSessionFactory <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//3.通过sqlSessionFactory创建SqlSession</span>
<span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="resources-getresourceasstream-resource-读取文件"><a href="#resources-getresourceasstream-resource-读取文件" class="header-anchor">#</a> Resources.getResourceAsStream(resource)读取文件</h3> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">InputStream</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token class-name">String</span> resource<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> 
<span class="token comment">//loader赋值为null</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">InputStream</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token class-name">ClassLoader</span> loader<span class="token punctuation">,</span> <span class="token class-name">String</span> resource<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{</span>
 <span class="token class-name">InputStream</span> in <span class="token operator">=</span> classLoaderWrapper<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span>resource<span class="token punctuation">,</span> loader<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>in <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IOException</span><span class="token punctuation">(</span><span class="token string">&quot;Could not find resource &quot;</span> <span class="token operator">+</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">return</span> in<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//classLoader为null</span>
<span class="token keyword">public</span> <span class="token class-name">InputStream</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token class-name">String</span> resource<span class="token punctuation">,</span> <span class="token class-name">ClassLoader</span> classLoader<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span>resource<span class="token punctuation">,</span> <span class="token function">getClassLoaders</span><span class="token punctuation">(</span>classLoader<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> 
<span class="token comment">//classLoader类加载</span>
<span class="token class-name">InputStream</span> <span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token class-name">String</span> resource<span class="token punctuation">,</span> <span class="token class-name">ClassLoader</span><span class="token punctuation">[</span><span class="token punctuation">]</span> classLoader<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">ClassLoader</span> cl <span class="token operator">:</span> classLoader<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">!=</span> cl<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">//加载指定路径文件流</span>
   <span class="token class-name">InputStream</span> returnValue <span class="token operator">=</span> cl<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token comment">// now, some class loaders want this leading &quot;/&quot;, so we'll add it and try again if we didn't find the resource</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">==</span> returnValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    returnValue <span class="token operator">=</span> cl<span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span> <span class="token operator">+</span> resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> 
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">!=</span> returnValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> returnValue<span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><p>总结：主要是通过ClassLoader.getResourceAsStream()方法获取指定的classpath路径下的Resource 。</p> <h3 id="通过sqlsessionfactorybuilder创建sqlsessionfactory"><a href="#通过sqlsessionfactorybuilder创建sqlsessionfactory" class="header-anchor">#</a> 通过SqlSessionFactoryBuilder创建SqlSessionFactory</h3> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//SqlSessionFactoryBuilder是一个建造者模式</span>
<span class="token class-name">SqlSessionFactory</span> sqlSessionFactory <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SqlSessionFactoryBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name">SqlSessionFactory</span> <span class="token function">build</span><span class="token punctuation">(</span><span class="token class-name">InputStream</span> inputStream<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token function">build</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//XMLConfigBuilder也是建造者模式</span>
<span class="token keyword">public</span> <span class="token class-name">SqlSessionFactory</span> <span class="token function">build</span><span class="token punctuation">(</span><span class="token class-name">InputStream</span> inputStream<span class="token punctuation">,</span> <span class="token class-name">String</span> environment<span class="token punctuation">,</span> <span class="token class-name">Properties</span> properties<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token class-name">XMLConfigBuilder</span> parser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLConfigBuilder</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span> environment<span class="token punctuation">,</span> properties<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token function">build</span><span class="token punctuation">(</span>parser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token class-name">ExceptionFactory</span><span class="token punctuation">.</span><span class="token function">wrapException</span><span class="token punctuation">(</span><span class="token string">&quot;Error building SqlSession.&quot;</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   inputStream<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IOException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">// Intentionally ignore. Prefer previous error.</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//接下来进入XMLConfigBuilder构造函数</span>
<span class="token keyword">public</span> <span class="token class-name">XMLConfigBuilder</span><span class="token punctuation">(</span><span class="token class-name">InputStream</span> inputStream<span class="token punctuation">,</span> <span class="token class-name">String</span> environment<span class="token punctuation">,</span> <span class="token class-name">Properties</span> props<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">this</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">XPathParser</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> props<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">XMLMapperEntityResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> environment<span class="token punctuation">,</span> props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//接下来进入this后,初始化Configuration</span>
<span class="token keyword">private</span> <span class="token class-name">XMLConfigBuilder</span><span class="token punctuation">(</span><span class="token class-name">XPathParser</span> parser<span class="token punctuation">,</span> <span class="token class-name">String</span> environment<span class="token punctuation">,</span> <span class="token class-name">Properties</span> props<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Configuration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">resource</span><span class="token punctuation">(</span><span class="token string">&quot;SQL Mapper Configuration&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>configuration<span class="token punctuation">.</span><span class="token function">setVariables</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>parsed <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>environment <span class="token operator">=</span> environment<span class="token punctuation">;</span>
 <span class="token keyword">this</span><span class="token punctuation">.</span>parser <span class="token operator">=</span> parser<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//其中parser.parse()负责解析xml,build(configuration)创建SqlSessionFactory</span>
<span class="token keyword">return</span> <span class="token function">build</span><span class="token punctuation">(</span>parser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br></div></div><h4 id="parser-parse-解析xml"><a href="#parser-parse-解析xml" class="header-anchor">#</a> parser.parse()解析xml</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">Configuration</span> <span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//判断是否重复解析</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>parsed<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BuilderException</span><span class="token punctuation">(</span><span class="token string">&quot;Each XMLConfigBuilder can only be used once.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 parsed <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
 <span class="token comment">//读取配置文件一级节点configuration</span>
 <span class="token function">parseConfiguration</span><span class="token punctuation">(</span>parser<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;/configuration&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">return</span> configuration<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">parseConfiguration</span><span class="token punctuation">(</span><span class="token class-name">XNode</span> root<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">//properties 标签,用来配置参数信息，比如最常见的数据库连接信息</span>
  <span class="token function">propertiesElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;properties&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token class-name">Properties</span> settings <span class="token operator">=</span> <span class="token function">settingsAsProperties</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;settings&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">loadCustomVfs</span><span class="token punctuation">(</span>settings<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">loadCustomLogImpl</span><span class="token punctuation">(</span>settings<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//实体别名两种方式:1.指定单个实体;2.指定包</span>
  <span class="token function">typeAliasesElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;typeAliases&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//插件</span>
  <span class="token function">pluginElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;plugins&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//用来创建对象(数据库数据映射成java对象时)</span>
  <span class="token function">objectFactoryElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;objectFactory&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">objectWrapperFactoryElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;objectWrapperFactory&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">reflectorFactoryElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;reflectorFactory&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">settingsElement</span><span class="token punctuation">(</span>settings<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// read it after objectFactory and objectWrapperFactory issue #631</span>
  <span class="token comment">//数据库环境</span>
  <span class="token function">environmentsElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;environments&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">databaseIdProviderElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;databaseIdProvider&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//数据库类型和Java数据类型的转换</span>
  <span class="token function">typeHandlerElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;typeHandlers&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//这个是对数据库增删改查的解析</span>
  <span class="token function">mapperElement</span><span class="token punctuation">(</span>root<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;mappers&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BuilderException</span><span class="token punctuation">(</span><span class="token string">&quot;Error parsing SQL Mapper Configuration. Cause: &quot;</span> <span class="token operator">+</span> e<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div><p>总结:parseConfiguration完成的是解析configuration下的标签</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">mapperElement</span><span class="token punctuation">(</span><span class="token class-name">XNode</span> parent<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>parent <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">XNode</span> child <span class="token operator">:</span> parent<span class="token punctuation">.</span><span class="token function">getChildren</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">//解析&lt;package name=&quot;&quot;/&gt;</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">&quot;package&quot;</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>child<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token class-name">String</span> mapperPackage <span class="token operator">=</span> child<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//包路径存到mapperRegistry中</span>
    configuration<span class="token punctuation">.</span><span class="token function">addMappers</span><span class="token punctuation">(</span>mapperPackage<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">//解析&lt;mapper url=&quot;&quot; class=&quot;&quot; resource=&quot;&quot;&gt;&lt;/mapper&gt;</span>
    <span class="token class-name">String</span> resource <span class="token operator">=</span> child<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resource&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> url <span class="token operator">=</span> child<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;url&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> mapperClass <span class="token operator">=</span> child<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;class&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>resource <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> url <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> mapperClass <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
     <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">resource</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//读取Mapper.xml文件</span>
     <span class="token class-name">InputStream</span> inputStream <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getResourceAsStream</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">XMLMapperBuilder</span> mapperParser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLMapperBuilder</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span>
     configuration<span class="token punctuation">,</span> resource<span class="token punctuation">,</span> configuration<span class="token punctuation">.</span><span class="token function">getSqlFragments</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     mapperParser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>resource <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> url <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> mapperClass <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
     <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">resource</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">InputStream</span> inputStream <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">getUrlAsStream</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">XMLMapperBuilder</span> mapperParser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLMapperBuilder</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span>
     configuration<span class="token punctuation">,</span> url<span class="token punctuation">,</span> configuration<span class="token punctuation">.</span><span class="token function">getSqlFragments</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     mapperParser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>resource <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> url <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> mapperClass <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
     <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> mapperInterface <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">classForName</span><span class="token punctuation">(</span>mapperClass<span class="token punctuation">)</span><span class="token punctuation">;</span>
     configuration<span class="token punctuation">.</span><span class="token function">addMapper</span><span class="token punctuation">(</span>mapperInterface<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
     <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BuilderException</span><span class="token punctuation">(</span><span class="token string">&quot;A mapper element may only specify a url, resource or class, but not more than one.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br></div></div><p>总结: 通过解析configuration.xml文件,获取其中的Environment、Setting,重要的是将下的所有解析出来之后添加到 Configuration,Configuration类似于配置中心,所有的配置信息都在这里。</p> <h4 id="mapperparser-parse-对-mapper-映射器的解析"><a href="#mapperparser-parse-对-mapper-映射器的解析" class="header-anchor">#</a> mapperParser.parse()对 Mapper 映射器的解析</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>configuration<span class="token punctuation">.</span><span class="token function">isResourceLoaded</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">//解析所有的子标签</span>
  <span class="token function">configurationElement</span><span class="token punctuation">(</span>parser<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;/mapper&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  configuration<span class="token punctuation">.</span><span class="token function">addLoadedResource</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//把namespace（接口类型）和工厂类绑定起来</span>
  <span class="token function">bindMapperForNamespace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
 <span class="token function">parsePendingResultMaps</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token function">parsePendingCacheRefs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token function">parsePendingStatements</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> 
<span class="token comment">//这里面解析的是Mapper.xml的标签</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">configurationElement</span><span class="token punctuation">(</span><span class="token class-name">XNode</span> context<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token class-name">String</span> namespace <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;namespace&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>namespace <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> namespace<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span><span class="token string">&quot;&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BuilderException</span><span class="token punctuation">(</span><span class="token string">&quot;Mapper's namespace cannot be empty&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  builderAssistant<span class="token punctuation">.</span><span class="token function">setCurrentNamespace</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//对其他命名空间缓存配置的引用</span>
  <span class="token function">cacheRefElement</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;cache-ref&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//对给定命名空间的缓存配置</span>
  <span class="token function">cacheElement</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNode</span><span class="token punctuation">(</span><span class="token string">&quot;cache&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">parameterMapElement</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNodes</span><span class="token punctuation">(</span><span class="token string">&quot;/mapper/parameterMap&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//是最复杂也是最强大的元素，用来描述如何从数据库结果集中来加载对象</span>
  <span class="token function">resultMapElements</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNodes</span><span class="token punctuation">(</span><span class="token string">&quot;/mapper/resultMap&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//可被其他语句引用的可重用语句块</span>
  <span class="token function">sqlElement</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNodes</span><span class="token punctuation">(</span><span class="token string">&quot;/mapper/sql&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//获得MappedStatement对象(增删改查标签)</span>
  <span class="token function">buildStatementFromContext</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">evalNodes</span><span class="token punctuation">(</span><span class="token string">&quot;select|insert|update|delete&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BuilderException</span><span class="token punctuation">(</span><span class="token string">&quot;Error parsing Mapper XML. The XML location is '&quot;</span> <span class="token operator">+</span> resource <span class="token operator">+</span> <span class="token string">&quot;'. Cause: &quot;</span> <span class="token operator">+</span> e<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//获得MappedStatement对象(增删改查标签)</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">buildStatementFromContext</span><span class="token punctuation">(</span><span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">XNode</span><span class="token punctuation">&gt;</span></span> list<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>configuration<span class="token punctuation">.</span><span class="token function">getDatabaseId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">buildStatementFromContext</span><span class="token punctuation">(</span>list<span class="token punctuation">,</span> configuration<span class="token punctuation">.</span><span class="token function">getDatabaseId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token function">buildStatementFromContext</span><span class="token punctuation">(</span>list<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//获得MappedStatement对象(增删改查标签)</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">buildStatementFromContext</span><span class="token punctuation">(</span><span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">XNode</span><span class="token punctuation">&gt;</span></span> list<span class="token punctuation">,</span> <span class="token class-name">String</span> requiredDatabaseId<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//循环增删改查标签</span>
 <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">XNode</span> context <span class="token operator">:</span> list<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">final</span> <span class="token class-name">XMLStatementBuilder</span> statementParser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLStatementBuilder</span><span class="token punctuation">(</span>configuration<span class="token punctuation">,</span> builderAssistant<span class="token punctuation">,</span> context<span class="token punctuation">,</span> requiredDatabaseId<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   <span class="token comment">//解析insert/update/select/del中的标签</span>
   statementParser<span class="token punctuation">.</span><span class="token function">parseStatementNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">IncompleteElementException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   configuration<span class="token punctuation">.</span><span class="token function">addIncompleteStatement</span><span class="token punctuation">(</span>statementParser<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">parseStatementNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//在命名空间中唯一的标识符,可以被用来引用这条语句</span>
 <span class="token class-name">String</span> id <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//数据库厂商标识</span>
 <span class="token class-name">String</span> databaseId <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;databaseId&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">databaseIdMatchesCurrent</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> databaseId<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>requiredDatabaseId<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token class-name">String</span> nodeName <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getNodeName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">SqlCommandType</span> sqlCommandType <span class="token operator">=</span>
 <span class="token class-name">SqlCommandType</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>nodeName<span class="token punctuation">.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token class-name">Locale</span><span class="token punctuation">.</span>ENGLISH<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">boolean</span> isSelect <span class="token operator">=</span> sqlCommandType <span class="token operator">==</span> <span class="token class-name">SqlCommandType</span><span class="token punctuation">.</span>SELECT<span class="token punctuation">;</span>
 <span class="token comment">//flushCache和useCache都和二级缓存有关</span>
 <span class="token comment">//将其设置为true后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false</span>
 <span class="token keyword">boolean</span> flushCache <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getBooleanAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;flushCache&quot;</span><span class="token punctuation">,</span> <span class="token operator">!</span>isSelect<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//将其设置为 true 后，将会导致本条语句的结果被二级缓存缓存起来，默认值：对 select 元素为 true</span>
 <span class="token keyword">boolean</span> useCache <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getBooleanAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;useCache&quot;</span><span class="token punctuation">,</span> isSelect<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">boolean</span> resultOrdered <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getBooleanAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resultOrdered&quot;</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">// Include Fragments before parsing</span>
 <span class="token class-name">XMLIncludeTransformer</span> includeParser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLIncludeTransformer</span><span class="token punctuation">(</span>configuration<span class="token punctuation">,</span> builderAssistant<span class="token punctuation">)</span><span class="token punctuation">;</span>
 includeParser<span class="token punctuation">.</span><span class="token function">applyIncludes</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">getNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//会传入这条语句的参数类的完全限定名或别名</span>
 <span class="token class-name">String</span> parameterType <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;parameterType&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> parameterTypeClass <span class="token operator">=</span> <span class="token function">resolveClass</span><span class="token punctuation">(</span>parameterType<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> lang <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;lang&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">LanguageDriver</span> langDriver <span class="token operator">=</span> <span class="token function">getLanguageDriver</span><span class="token punctuation">(</span>lang<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">// Parse selectKey after includes and remove them.</span>
 <span class="token function">processSelectKeyNodes</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> parameterTypeClass<span class="token punctuation">,</span> langDriver<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">// Parse the SQL (pre: &lt;selectKey&gt; and &lt;include&gt; were parsed and removed)</span>
 <span class="token class-name">KeyGenerator</span> keyGenerator<span class="token punctuation">;</span>
 <span class="token class-name">String</span> keyStatementId <span class="token operator">=</span> id <span class="token operator">+</span> <span class="token class-name">SelectKeyGenerator</span><span class="token punctuation">.</span>SELECT_KEY_SUFFIX<span class="token punctuation">;</span>
 keyStatementId <span class="token operator">=</span> builderAssistant<span class="token punctuation">.</span><span class="token function">applyCurrentNamespace</span><span class="token punctuation">(</span>keyStatementId<span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>configuration<span class="token punctuation">.</span><span class="token function">hasKeyGenerator</span><span class="token punctuation">(</span>keyStatementId<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  keyGenerator <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">getKeyGenerator</span><span class="token punctuation">(</span>keyStatementId<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
  keyGenerator <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getBooleanAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;useGeneratedKeys&quot;</span><span class="token punctuation">,</span> configuration<span class="token punctuation">.</span><span class="token function">isUseGeneratedKeys</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token class-name">SqlCommandType</span><span class="token punctuation">.</span>INSERT<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>sqlCommandType<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token class-name">Jdbc3KeyGenerator</span><span class="token punctuation">.</span>INSTANCE <span class="token operator">:</span> <span class="token class-name">NoKeyGenerator</span><span class="token punctuation">.</span>INSTANCE<span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token class-name">SqlSource</span> sqlSource <span class="token operator">=</span> langDriver<span class="token punctuation">.</span><span class="token function">createSqlSource</span><span class="token punctuation">(</span>configuration<span class="token punctuation">,</span> context<span class="token punctuation">,</span> parameterTypeClass<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">StatementType</span> statementType <span class="token operator">=</span>
 <span class="token class-name">StatementType</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;statementType&quot;</span><span class="token punctuation">,</span>
 <span class="token class-name">StatementType</span><span class="token punctuation">.</span>PREPARED<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">Integer</span> fetchSize <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getIntAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;fetchSize&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">Integer</span> timeout <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getIntAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;timeout&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> parameterMap <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;parameterMap&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//从这条语句中返回的期望类型的类的完全限定名或别名</span>
 <span class="token class-name">String</span> resultType <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resultType&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> resultTypeClass <span class="token operator">=</span> <span class="token function">resolveClass</span><span class="token punctuation">(</span>resultType<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//外部resultMap的命名引用</span>
 <span class="token class-name">String</span> resultMap <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resultMap&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> resultSetType <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resultSetType&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">ResultSetType</span> resultSetTypeEnum <span class="token operator">=</span> <span class="token function">resolveResultSetType</span><span class="token punctuation">(</span>resultSetType<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> keyProperty <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;keyProperty&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> keyColumn <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;keyColumn&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token class-name">String</span> resultSets <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">getStringAttribute</span><span class="token punctuation">(</span><span class="token string">&quot;resultSets&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 builderAssistant<span class="token punctuation">.</span><span class="token function">addMappedStatement</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> sqlSource<span class="token punctuation">,</span> statementType<span class="token punctuation">,</span> sqlCommandType<span class="token punctuation">,</span>
 fetchSize<span class="token punctuation">,</span> timeout<span class="token punctuation">,</span> parameterMap<span class="token punctuation">,</span> parameterTypeClass<span class="token punctuation">,</span> resultMap<span class="token punctuation">,</span> resultTypeClass<span class="token punctuation">,</span>
 resultSetTypeEnum<span class="token punctuation">,</span> flushCache<span class="token punctuation">,</span> useCache<span class="token punctuation">,</span> resultOrdered<span class="token punctuation">,</span>
 keyGenerator<span class="token punctuation">,</span> keyProperty<span class="token punctuation">,</span> keyColumn<span class="token punctuation">,</span> databaseId<span class="token punctuation">,</span> langDriver<span class="token punctuation">,</span> resultSets<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">MappedStatement</span> <span class="token function">addMappedStatement</span><span class="token punctuation">(</span>
 <span class="token class-name">String</span> id<span class="token punctuation">,</span>
 <span class="token class-name">SqlSource</span> sqlSource<span class="token punctuation">,</span>
 <span class="token class-name">StatementType</span> statementType<span class="token punctuation">,</span>
 <span class="token class-name">SqlCommandType</span> sqlCommandType<span class="token punctuation">,</span>
 <span class="token class-name">Integer</span> fetchSize<span class="token punctuation">,</span>
 <span class="token class-name">Integer</span> timeout<span class="token punctuation">,</span>
 <span class="token class-name">String</span> parameterMap<span class="token punctuation">,</span>
 <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> parameterType<span class="token punctuation">,</span>
 <span class="token class-name">String</span> resultMap<span class="token punctuation">,</span>
 <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> resultType<span class="token punctuation">,</span>
 <span class="token class-name">ResultSetType</span> resultSetType<span class="token punctuation">,</span>
 <span class="token keyword">boolean</span> flushCache<span class="token punctuation">,</span>
 <span class="token keyword">boolean</span> useCache<span class="token punctuation">,</span>
 <span class="token keyword">boolean</span> resultOrdered<span class="token punctuation">,</span>
 <span class="token class-name">KeyGenerator</span> keyGenerator<span class="token punctuation">,</span>
 <span class="token class-name">String</span> keyProperty<span class="token punctuation">,</span>
 <span class="token class-name">String</span> keyColumn<span class="token punctuation">,</span>
 <span class="token class-name">String</span> databaseId<span class="token punctuation">,</span>
 <span class="token class-name">LanguageDriver</span> lang<span class="token punctuation">,</span>
 <span class="token class-name">String</span> resultSets<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>unresolvedCacheRef<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IncompleteElementException</span><span class="token punctuation">(</span><span class="token string">&quot;Cache-ref not yet resolved&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
  id <span class="token operator">=</span> <span class="token function">applyCurrentNamespace</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">boolean</span> isSelect <span class="token operator">=</span> sqlCommandType <span class="token operator">==</span> <span class="token class-name">SqlCommandType</span><span class="token punctuation">.</span>SELECT<span class="token punctuation">;</span>
  <span class="token class-name">MappedStatement<span class="token punctuation">.</span>Builder</span> statementBuilder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MappedStatement<span class="token punctuation">.</span>Builder</span><span class="token punctuation">(</span>configuration<span class="token punctuation">,</span>
  id<span class="token punctuation">,</span> sqlSource<span class="token punctuation">,</span> sqlCommandType<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">resource</span><span class="token punctuation">(</span>resource<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">fetchSize</span><span class="token punctuation">(</span>fetchSize<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">timeout</span><span class="token punctuation">(</span>timeout<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">statementType</span><span class="token punctuation">(</span>statementType<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">keyGenerator</span><span class="token punctuation">(</span>keyGenerator<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">keyProperty</span><span class="token punctuation">(</span>keyProperty<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">keyColumn</span><span class="token punctuation">(</span>keyColumn<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">databaseId</span><span class="token punctuation">(</span>databaseId<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">lang</span><span class="token punctuation">(</span>lang<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">resultOrdered</span><span class="token punctuation">(</span>resultOrdered<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">resultSets</span><span class="token punctuation">(</span>resultSets<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">resultMaps</span><span class="token punctuation">(</span><span class="token function">getStatementResultMaps</span><span class="token punctuation">(</span>resultMap<span class="token punctuation">,</span> resultType<span class="token punctuation">,</span> id<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">resultSetType</span><span class="token punctuation">(</span>resultSetType<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">flushCacheRequired</span><span class="token punctuation">(</span><span class="token function">valueOrDefault</span><span class="token punctuation">(</span>flushCache<span class="token punctuation">,</span> <span class="token operator">!</span>isSelect<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">useCache</span><span class="token punctuation">(</span><span class="token function">valueOrDefault</span><span class="token punctuation">(</span>useCache<span class="token punctuation">,</span> isSelect<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">cache</span><span class="token punctuation">(</span>currentCache<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token class-name">ParameterMap</span> statementParameterMap <span class="token operator">=</span> <span class="token function">getStatementParameterMap</span><span class="token punctuation">(</span>parameterMap<span class="token punctuation">,</span>
  parameterType<span class="token punctuation">,</span> id<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>statementParameterMap <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   statementBuilder<span class="token punctuation">.</span><span class="token function">parameterMap</span><span class="token punctuation">(</span>statementParameterMap<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token class-name">MappedStatement</span> statement <span class="token operator">=</span> statementBuilder<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//持有在configuration中</span>
  configuration<span class="token punctuation">.</span><span class="token function">addMappedStatement</span><span class="token punctuation">(</span>statement<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> statement<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addMappedStatement</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token comment">//ms.getId = mapper.UserMapper.getUserById</span>
<span class="token comment">//ms = MappedStatement等于每一个增删改查的标签的里的数据</span>
 mappedStatements<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>ms<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">//最终存放到mappedStatements中,mappedStatements存放的是一个个的增删改查</span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">MappedStatement</span><span class="token punctuation">&gt;</span></span> mappedStatements <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StrictMap</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">MappedStatement</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token string">&quot;Mapped Statements collection&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">conflictMessageProducer</span><span class="token punctuation">(</span><span class="token punctuation">(</span>savedValue<span class="token punctuation">,</span> targetValue<span class="token punctuation">)</span> <span class="token operator">-&gt;</span>
<span class="token string">&quot;. please check &quot;</span> <span class="token operator">+</span> savedValue<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot; and &quot;</span> <span class="token operator">+</span> targetValue<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br></div></div><h4 id="解析bindmapperfornamespace-方法"><a href="#解析bindmapperfornamespace-方法" class="header-anchor">#</a> 解析bindMapperForNamespace()方法</h4> <p>把 namespace（接口类型）和工厂类绑定起来</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">bindMapperForNamespace</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//当前Mapper的命名空间</span>
 <span class="token class-name">String</span> namespace <span class="token operator">=</span> builderAssistant<span class="token punctuation">.</span><span class="token function">getCurrentNamespace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>namespace <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> boundType <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   <span class="token comment">//interface mapper.UserMapper这种</span>
   boundType <span class="token operator">=</span> <span class="token class-name">Resources</span><span class="token punctuation">.</span><span class="token function">classForName</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ClassNotFoundException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token punctuation">}</span> 
  <span class="token keyword">if</span> <span class="token punctuation">(</span>boundType <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>configuration<span class="token punctuation">.</span><span class="token function">hasMapper</span><span class="token punctuation">(</span>boundType<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    configuration<span class="token punctuation">.</span><span class="token function">addLoadedResource</span><span class="token punctuation">(</span><span class="token string">&quot;namespace:&quot;</span> <span class="token operator">+</span> namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
    configuration<span class="token punctuation">.</span><span class="token function">addMapper</span><span class="token punctuation">(</span>boundType<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token keyword">void</span> <span class="token function">addMapper</span><span class="token punctuation">(</span><span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 mapperRegistry<span class="token punctuation">.</span><span class="token function">addMapper</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> 
<span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token keyword">void</span> <span class="token function">addMapper</span><span class="token punctuation">(</span><span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>type<span class="token punctuation">.</span><span class="token function">isInterface</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">hasMapper</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingException</span><span class="token punctuation">(</span><span class="token string">&quot;Type &quot;</span> <span class="token operator">+</span> type <span class="token operator">+</span> <span class="token string">&quot; is already known to the MapperRegistry.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token keyword">boolean</span> loadCompleted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
   <span class="token comment">//接口类型(key)-&gt;工厂类</span>
   knownMappers<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MapperProxyFactory</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token class-name">MapperAnnotationBuilder</span> parser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MapperAnnotationBuilder</span><span class="token punctuation">(</span>config<span class="token punctuation">,</span> type<span class="token punctuation">)</span><span class="token punctuation">;</span>
   parser<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   loadCompleted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>loadCompleted<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    knownMappers<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><h4 id="生成sqlsessionfactory对象"><a href="#生成sqlsessionfactory对象" class="header-anchor">#</a> 生成SqlSessionFactory对象</h4> <p>XMLMapperBuilder.parse()方法,是对 Mapper 映射器的解析里面有两个方法：</p> <p>（1）configurationElement()解析所有的子标签,最终解析Mapper.xml中的insert/update/delete/select标签的id(全路径)组成key和整个标签和数据连接组成MappedStatement存放到Configuration中的 mappedStatements这个map里面。</p> <p>（2）bindMapperForNamespace()是把接口类型(interface mapper.UserMapper)和工厂类存到放MapperRegistry中的knownMappers里面。</p> <h2 id="sqlsessionfactory的创建"><a href="#sqlsessionfactory的创建" class="header-anchor">#</a> SqlSessionFactory的创建</h2> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">SqlSessionFactory</span> <span class="token function">build</span><span class="token punctuation">(</span><span class="token class-name">Configuration</span> config<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DefaultSqlSessionFactory</span><span class="token punctuation">(</span>config<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>直接把Configuration当做参数,直接new一个DefaultSqlSessionFactory。</p> <h2 id="sqlsession会话的创建过程"><a href="#sqlsession会话的创建过程" class="header-anchor">#</a> SqlSession会话的创建过程</h2> <p>mybatis操作的时候跟数据库的每一次连接,都需要创建一个会话,我们用openSession()方法来创建。这个会话里面需要包含一个Executor用来执行 SQL。Executor又要指定事务类型和执行器的类型。</p> <h3 id="创建transaction-两种方式"><a href="#创建transaction-两种方式" class="header-anchor">#</a> 创建Transaction(两种方式)</h3> <table><thead><tr><th style="text-align:left;">属性</th> <th style="text-align:left;">产生工厂类</th> <th style="text-align:left;">产生事务</th></tr></thead> <tbody><tr><td style="text-align:left;">JDBC</td> <td style="text-align:left;">JbdcTransactionFactory</td> <td style="text-align:left;">JdbcTransaction</td></tr> <tr><td style="text-align:left;">MANAGED</td> <td style="text-align:left;">ManagedTransactionFactory</td> <td style="text-align:left;">ManagedTransaction</td></tr></tbody></table> <ul><li>如果配置的是 JDBC,则会使用Connection 对象的 commit()、rollback()、close()管理事务。</li> <li>如果配置成MANAGED,会把事务交给容器来管理,比如 JBOSS,Weblogic。</li></ul> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">SqlSession</span> sqlSession <span class="token operator">=</span> sqlSessionFactory<span class="token punctuation">.</span><span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token class-name">SqlSession</span> <span class="token function">openSession</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//configuration中有默认赋值protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE</span>
 <span class="token keyword">return</span> <span class="token function">openSessionFromDataSource</span><span class="token punctuation">(</span>configuration<span class="token punctuation">.</span><span class="token function">getDefaultExecutorType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token operator">&lt;</span>environments <span class="token keyword">default</span><span class="token operator">=</span><span class="token string">&quot;development&quot;</span><span class="token operator">&gt;</span>
 <span class="token operator">&lt;</span>environment id<span class="token operator">=</span><span class="token string">&quot;development&quot;</span><span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>transactionManager type<span class="token operator">=</span><span class="token string">&quot;JDBC&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>dataSource type<span class="token operator">=</span><span class="token string">&quot;POOLED&quot;</span><span class="token operator">&gt;</span>
   <span class="token operator">&lt;</span>property name<span class="token operator">=</span><span class="token string">&quot;driver&quot;</span> value<span class="token operator">=</span><span class="token string">&quot;${driver}&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
   <span class="token operator">&lt;</span>property name<span class="token operator">=</span><span class="token string">&quot;url&quot;</span> value<span class="token operator">=</span><span class="token string">&quot;${url}&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
   <span class="token operator">&lt;</span>property name<span class="token operator">=</span><span class="token string">&quot;username&quot;</span> value<span class="token operator">=</span><span class="token string">&quot;${username}&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
   <span class="token operator">&lt;</span>property name<span class="token operator">=</span><span class="token string">&quot;password&quot;</span> value<span class="token operator">=</span><span class="token string">&quot;${password}&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>dataSource<span class="token operator">&gt;</span>
 <span class="token operator">&lt;</span><span class="token operator">/</span>environment<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>environments<span class="token operator">&gt;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><h3 id="创建executor"><a href="#创建executor" class="header-anchor">#</a> 创建Executor</h3> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//ExecutorType是SIMPLE,一共有三种SIMPLE(SimpleExecutor)、REUSE(ReuseExecutor)、BATCH(BatchExecutor)</span>
<span class="token keyword">private</span> <span class="token class-name">SqlSession</span> <span class="token function">openSessionFromDataSource</span><span class="token punctuation">(</span><span class="token class-name">ExecutorType</span> execType<span class="token punctuation">,</span> <span class="token class-name">TransactionIsolationLevel</span> level<span class="token punctuation">,</span> <span class="token keyword">boolean</span> autoCommit<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token class-name">Transaction</span> tx <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">//xml中的development节点</span>
  <span class="token keyword">final</span> <span class="token class-name">Environment</span> environment <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">getEnvironment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//type配置的是Jbdc所以生成的是JbdcTransactionFactory工厂类</span>
  <span class="token keyword">final</span> <span class="token class-name">TransactionFactory</span> transactionFactory <span class="token operator">=</span> <span class="token function">getTransactionFactoryFromEnvironment</span><span class="token punctuation">(</span>environment<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//Jdbc生成JbdcTransactionFactory生成JbdcTransaction</span>
  tx <span class="token operator">=</span> transactionFactory<span class="token punctuation">.</span><span class="token function">newTransaction</span><span class="token punctuation">(</span>environment<span class="token punctuation">.</span><span class="token function">getDataSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> level<span class="token punctuation">,</span> autoCommit<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//创建CachingExecutor执行器</span>
  <span class="token keyword">final</span> <span class="token class-name">Executor</span> executor <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">newExecutor</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> execType<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//创建DefaultSqlSession属性包括 Configuration、Executor对象</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DefaultSqlSession</span><span class="token punctuation">(</span>configuration<span class="token punctuation">,</span> executor<span class="token punctuation">,</span> autoCommit<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">closeTransaction</span><span class="token punctuation">(</span>tx<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// may have fetched a connection so lets call</span>
  <span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">throw</span> <span class="token class-name">ExceptionFactory</span><span class="token punctuation">.</span><span class="token function">wrapException</span><span class="token punctuation">(</span><span class="token string">&quot;Error opening session. Cause: &quot;</span> <span class="token operator">+</span> e<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><h2 id="获得mapper对象"><a href="#获得mapper对象" class="header-anchor">#</a> 获得Mapper对象</h2> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">UserMapper</span> userMapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">UserMapper</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">T</span> <span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> configuration<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>mapperRegistry.getMapper是从MapperRegistry的knownMappers里面取的,knownMappers里面存的是接口类型(interface mapper.UserMapper)和工厂类(MapperProxyFactory)。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">T</span> <span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> type<span class="token punctuation">,</span> <span class="token class-name">SqlSession</span> sqlSession<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> mapperRegistry<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> sqlSession<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>从knownMappers的Map里根据接口类型(interface mapper.UserMapper)取出对应的工厂类。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">T</span> <span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">Class</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> type<span class="token punctuation">,</span> <span class="token class-name">SqlSession</span> sqlSession<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">final</span> <span class="token class-name">MapperProxyFactory</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> mapperProxyFactory <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">MapperProxyFactory</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">)</span>
 knownMappers<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>mapperProxyFactory <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingException</span><span class="token punctuation">(</span><span class="token string">&quot;Type &quot;</span> <span class="token operator">+</span> type <span class="token operator">+</span> <span class="token string">&quot; is not known to the MapperRegistry.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> mapperProxyFactory<span class="token punctuation">.</span><span class="token function">newInstance</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingException</span><span class="token punctuation">(</span><span class="token string">&quot;Error getting mapper instance. Cause: &quot;</span> <span class="token operator">+</span> e<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">T</span> <span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token class-name">SqlSession</span> sqlSession<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">final</span> <span class="token class-name">MapperProxy</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> mapperProxy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MapperProxy</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> mapperInterface<span class="token punctuation">,</span> methodCache<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">return</span> <span class="token function">newInstance</span><span class="token punctuation">(</span>mapperProxy<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>这里通过JDK动态代理返回代理对象MapperProxy(org.apache.ibatis.binding.MapperProxy@6b2ea799)</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">protected</span> <span class="token class-name">T</span> <span class="token function">newInstance</span><span class="token punctuation">(</span><span class="token class-name">MapperProxy</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> mapperProxy<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">//mapperInterface是interface mapper.UserMapper </span>
 <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token class-name">T</span><span class="token punctuation">)</span> <span class="token class-name">Proxy</span><span class="token punctuation">.</span><span class="token function">newProxyInstance</span><span class="token punctuation">(</span>mapperInterface<span class="token punctuation">.</span><span class="token function">getClassLoader</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span>
 <span class="token class-name">Class</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> mapperInterface <span class="token punctuation">}</span><span class="token punctuation">,</span> mapperProxy<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">UserMapper</span> userMapper <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">getMapper</span><span class="token punctuation">(</span><span class="token class-name">UserMapper</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h2 id="执行sql"><a href="#执行sql" class="header-anchor">#</a> 执行SQL</h2> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">User</span> user <span class="token operator">=</span> userMapper<span class="token punctuation">.</span><span class="token function">getUserById</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h3 id="调用invoke代理方法"><a href="#调用invoke代理方法" class="header-anchor">#</a> 调用invoke代理方法</h3> <p>由于所有的 Mapper 都是 MapperProxy 代理对象，所以任意的方法都是执行MapperProxy 的invoke()方法</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">invoke</span><span class="token punctuation">(</span><span class="token class-name">Object</span> proxy<span class="token punctuation">,</span> <span class="token class-name">Method</span> method<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">//判断是否需要去执行SQL还是直接执行方法</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Object</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">getDeclaringClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">return</span> method<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token comment">//这里判断的是接口中的默认方法Default等</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isDefaultMethod</span><span class="token punctuation">(</span>method<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token keyword">return</span> <span class="token function">invokeDefaultMethod</span><span class="token punctuation">(</span>proxy<span class="token punctuation">,</span> method<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> t<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token class-name">ExceptionUtil</span><span class="token punctuation">.</span><span class="token function">unwrapThrowable</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
    <span class="token comment">//获取缓存,保存了方法签名和接口方法的关系</span>
 <span class="token keyword">final</span> <span class="token class-name">MapperMethod</span> mapperMethod <span class="token operator">=</span> <span class="token function">cachedMapperMethod</span><span class="token punctuation">(</span>method<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">return</span> mapperMethod<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><h3 id="调用execute方法"><a href="#调用execute方法" class="header-anchor">#</a> 调用execute方法</h3> <p>这里使用的例子用的是查询所以走的是else分支语句。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token class-name">SqlSession</span> sqlSession<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token class-name">Object</span> result<span class="token punctuation">;</span>
 <span class="token comment">//根据命令类型走不行的操作command.getType()是select</span>
 <span class="token keyword">switch</span> <span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">getType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">case</span> INSERT<span class="token operator">:</span> <span class="token punctuation">{</span>
   <span class="token class-name">Object</span> param <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">convertArgsToSqlCommandParam</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   result <span class="token operator">=</span> <span class="token function">rowCountResult</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> param<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">break</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token keyword">case</span> UPDATE<span class="token operator">:</span> <span class="token punctuation">{</span>
   <span class="token class-name">Object</span> param <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">convertArgsToSqlCommandParam</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   result <span class="token operator">=</span> <span class="token function">rowCountResult</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> param<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">break</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token keyword">case</span> DELETE<span class="token operator">:</span> <span class="token punctuation">{</span>
   <span class="token class-name">Object</span> param <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">convertArgsToSqlCommandParam</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   result <span class="token operator">=</span> <span class="token function">rowCountResult</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> param<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">break</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token keyword">case</span> SELECT<span class="token operator">:</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">returnsVoid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> method<span class="token punctuation">.</span><span class="token function">hasResultHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">executeWithResultHandler</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    result <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">returnsMany</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    result <span class="token operator">=</span> <span class="token function">executeForMany</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">returnsMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    result <span class="token operator">=</span> <span class="token function">executeForMap</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">returnsCursor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    result <span class="token operator">=</span> <span class="token function">executeForCursor</span><span class="token punctuation">(</span>sqlSession<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">//将参数转换为SQL的参数</span>
    <span class="token class-name">Object</span> param <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">convertArgsToSqlCommandParam</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    result <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">selectOne</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> param<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>method<span class="token punctuation">.</span><span class="token function">returnsOptional</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span>
    <span class="token operator">!</span>method<span class="token punctuation">.</span><span class="token function">getReturnType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
     result <span class="token operator">=</span> <span class="token class-name">Optional</span><span class="token punctuation">.</span><span class="token function">ofNullable</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
   <span class="token punctuation">}</span>
   <span class="token keyword">break</span><span class="token punctuation">;</span>
  <span class="token keyword">case</span> FLUSH<span class="token operator">:</span>
   result <span class="token operator">=</span> sqlSession<span class="token punctuation">.</span><span class="token function">flushStatements</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">break</span><span class="token punctuation">;</span>
  <span class="token keyword">default</span><span class="token operator">:</span>
   <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingException</span><span class="token punctuation">(</span><span class="token string">&quot;Unknown execution method for: &quot;</span> <span class="token operator">+</span> command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> method<span class="token punctuation">.</span><span class="token function">getReturnType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isPrimitive</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>method<span class="token punctuation">.</span><span class="token function">returnsVoid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BindingException</span><span class="token punctuation">(</span><span class="token string">&quot;Mapper method '&quot;</span> <span class="token operator">+</span> command<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot; attempted to return null from a method with a primitive return type (&quot;</span> <span class="token operator">+</span> method<span class="token punctuation">.</span><span class="token function">getReturnType</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot;).&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br></div></div><h3 id="调用selectone其实是selectlist"><a href="#调用selectone其实是selectlist" class="header-anchor">#</a> 调用selectOne其实是selectList</h3> <p>selectOne查询一个和查询多个其实是一样的。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">T</span> <span class="token function">selectOne</span><span class="token punctuation">(</span><span class="token class-name">String</span> statement<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameter<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token comment">// Popular vote was to return null on 0 results and throw exception on too many.</span>
 <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">T</span><span class="token punctuation">&gt;</span></span> list <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">selectList</span><span class="token punctuation">(</span>statement<span class="token punctuation">,</span> parameter<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TooManyResultsException</span><span class="token punctuation">(</span><span class="token string">&quot;Expected one result (or null) to be returned by selectOne(), but found: &quot;</span> <span class="token operator">+</span> list<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">selectList</span><span class="token punctuation">(</span><span class="token class-name">String</span> statement<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameter<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">//从Configuration里的mappedStatements里根据key(id的全路径)获取MappedStatement 对象</span>
  <span class="token class-name">MappedStatement</span> ms <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">getMappedStatement</span><span class="token punctuation">(</span>statement<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> executor<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> <span class="token function">wrapCollection</span><span class="token punctuation">(</span>parameter<span class="token punctuation">)</span><span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">Executor</span><span class="token punctuation">.</span>NO_RESULT_HANDLER<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token class-name">ExceptionFactory</span><span class="token punctuation">.</span><span class="token function">wrapException</span><span class="token punctuation">(</span><span class="token string">&quot;Error querying database. Cause: &quot;</span> <span class="token operator">+</span> e<span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><h4 id="mappedstatements对象如图"><a href="#mappedstatements对象如图" class="header-anchor">#</a> mappedStatements对象如图</h4> <p><img alt="" data-src="https://img-blog.csdnimg.cn/img_convert/8a4207c6d43cd0e5c07bfd9eb9c00f62.png" loading="lazy" class="lazy"></p> <h4 id="mappedstatement对象如图"><a href="#mappedstatement对象如图" class="header-anchor">#</a> MappedStatement对象如图</h4> <p><img alt="" data-src="https://img-blog.csdnimg.cn/img_convert/cc54230efe10651edd6c7596cb5390e2.png" loading="lazy" class="lazy"></p> <h3 id="执行query方法"><a href="#执行query方法" class="header-anchor">#</a> 执行query方法</h3> <h4 id="创建cachekey"><a href="#创建cachekey" class="header-anchor">#</a> 创建CacheKey</h4> <p>从 BoundSql 中获取SQL信息,创建 CacheKey。这个CacheKey就是缓存的Key。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameterObject<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">ResultHandler</span> resultHandler<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">SQLException</span> <span class="token punctuation">{</span>
 <span class="token comment">//创建缓存Key</span>
 <span class="token class-name">BoundSql</span> boundSql <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">getBoundSql</span><span class="token punctuation">(</span>parameterObject<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token comment">//key = -575461213:-771016147:mapper.UserMapper.getUserById:0:2147483647:select * from test_user where id = ?:1:development</span>
 <span class="token class-name">CacheKey</span> key <span class="token operator">=</span> <span class="token function">createCacheKey</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameterObject<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">return</span> <span class="token function">query</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameterObject<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> key<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameterObject<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">ResultHandler</span> resultHandler<span class="token punctuation">,</span> <span class="token class-name">CacheKey</span> key<span class="token punctuation">,</span> <span class="token class-name">BoundSql</span> boundSql<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">SQLException</span> <span class="token punctuation">{</span>
 <span class="token class-name">Cache</span> cache <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">getCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>cache <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">flushCacheIfRequired</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>ms<span class="token punctuation">.</span><span class="token function">isUseCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> resultHandler <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token function">ensureNoOutParams</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token annotation punctuation">@SuppressWarnings</span><span class="token punctuation">(</span><span class="token string">&quot;unchecked&quot;</span><span class="token punctuation">)</span>
   <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> list <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">)</span> tcm<span class="token punctuation">.</span><span class="token function">getObject</span><span class="token punctuation">(</span>cache<span class="token punctuation">,</span> key<span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    list <span class="token operator">=</span> delegate<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameterObject<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> key<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
    tcm<span class="token punctuation">.</span><span class="token function">putObject</span><span class="token punctuation">(</span>cache<span class="token punctuation">,</span> key<span class="token punctuation">,</span> list<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// issue #578 and #116</span>
   <span class="token punctuation">}</span> 
   <span class="token keyword">return</span> list<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
 <span class="token keyword">return</span> delegate<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameterObject<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> key<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><h4 id="清空本地缓存"><a href="#清空本地缓存" class="header-anchor">#</a> 清空本地缓存</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameter<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">ResultHandler</span> resultHandler<span class="token punctuation">,</span> <span class="token class-name">CacheKey</span> key<span class="token punctuation">,</span> <span class="token class-name">BoundSql</span> boundSql<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">SQLException</span> <span class="token punctuation">{</span>
 <span class="token class-name">ErrorContext</span><span class="token punctuation">.</span><span class="token function">instance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">resource</span><span class="token punctuation">(</span>ms<span class="token punctuation">.</span><span class="token function">getResource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">activity</span><span class="token punctuation">(</span><span class="token string">&quot;executing a query&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">object</span><span class="token punctuation">(</span>ms<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>closed<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ExecutorException</span><span class="token punctuation">(</span><span class="token string">&quot;Executor was closed.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token comment">//queryStack 用于记录查询栈，防止递归查询重复处理缓存</span>
 <span class="token comment">//flushCache=true 的时候，会先清理本地缓存（一级缓存）</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>queryStack <span class="token operator">==</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> ms<span class="token punctuation">.</span><span class="token function">isFlushCacheRequired</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">//清空本地缓存</span>
  <span class="token function">clearLocalCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> list<span class="token punctuation">;</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  queryStack<span class="token operator">++</span><span class="token punctuation">;</span>
  list <span class="token operator">=</span> resultHandler <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">?</span> <span class="token punctuation">(</span><span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">)</span> localCache<span class="token punctuation">.</span><span class="token function">getObject</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>list <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token function">handleLocallyCachedOutputParameters</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> key<span class="token punctuation">,</span> parameter<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
   <span class="token comment">//如果没有缓存,会从数据库查询：queryFromDatabase()</span>
   list <span class="token operator">=</span> <span class="token function">queryFromDatabase</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameter<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> key<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  queryStack<span class="token operator">--</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">if</span> <span class="token punctuation">(</span>queryStack <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">DeferredLoad</span> deferredLoad <span class="token operator">:</span> deferredLoads<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  deferredLoad<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> 
  <span class="token comment">// issue #601</span>
  deferredLoads<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">//如果 LocalCacheScope == STATEMENT,会清理本地缓存</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>configuration<span class="token punctuation">.</span><span class="token function">getLocalCacheScope</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token class-name">LocalCacheScope</span><span class="token punctuation">.</span>STATEMENT<span class="token punctuation">)</span> <span class="token punctuation">{</span>
   <span class="token comment">// issue #482</span>
   <span class="token function">clearLocalCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">return</span> list<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br></div></div><h4 id="从数据库查询"><a href="#从数据库查询" class="header-anchor">#</a> 从数据库查询</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">queryFromDatabase</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameter<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">ResultHandler</span> resultHandler<span class="token punctuation">,</span> <span class="token class-name">CacheKey</span> key<span class="token punctuation">,</span> <span class="token class-name">BoundSql</span> boundSql<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">SQLException</span> <span class="token punctuation">{</span>
 <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> list<span class="token punctuation">;</span>
 <span class="token comment">//先在缓存用占位符占位</span>
 localCache<span class="token punctuation">.</span><span class="token function">putObject</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> EXECUTION_PLACEHOLDER<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token comment">//执行Executor 的 doQuery(),默认是SimpleExecutor</span>
  list <span class="token operator">=</span> <span class="token function">doQuery</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> parameter<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token comment">//执行查询后,移除占位符</span>
  localCache<span class="token punctuation">.</span><span class="token function">removeObject</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token comment">//从新放入数据</span>
 localCache<span class="token punctuation">.</span><span class="token function">putObject</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> list<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">if</span> <span class="token punctuation">(</span>ms<span class="token punctuation">.</span><span class="token function">getStatementType</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token class-name">StatementType</span><span class="token punctuation">.</span>CALLABLE<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  localOutputParameterCache<span class="token punctuation">.</span><span class="token function">putObject</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> parameter<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> 
 <span class="token keyword">return</span> list<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><h4 id="执行doquery"><a href="#执行doquery" class="header-anchor">#</a> 执行doQuery</h4> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">E</span><span class="token punctuation">&gt;</span></span> <span class="token function">doQuery</span><span class="token punctuation">(</span><span class="token class-name">MappedStatement</span> ms<span class="token punctuation">,</span> <span class="token class-name">Object</span> parameter<span class="token punctuation">,</span> <span class="token class-name">RowBounds</span> rowBounds<span class="token punctuation">,</span> <span class="token class-name">ResultHandler</span> resultHandler<span class="token punctuation">,</span> <span class="token class-name">BoundSql</span> boundSql<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">SQLException</span> <span class="token punctuation">{</span>
 <span class="token class-name">Statement</span> stmt <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
 <span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token class-name">Configuration</span> configuration <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">getConfiguration</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token class-name">StatementHandler</span> handler <span class="token operator">=</span> configuration<span class="token punctuation">.</span><span class="token function">newStatementHandler</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">,</span> ms<span class="token punctuation">,</span> parameter<span class="token punctuation">,</span> rowBounds<span class="token punctuation">,</span> resultHandler<span class="token punctuation">,</span> boundSql<span class="token punctuation">)</span><span class="token punctuation">;</span>
  stmt <span class="token operator">=</span> <span class="token function">prepareStatement</span><span class="token punctuation">(</span>handler<span class="token punctuation">,</span> ms<span class="token punctuation">.</span><span class="token function">getStatementLog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> handler<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>stmt<span class="token punctuation">,</span> resultHandler<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
  <span class="token function">closeStatement</span><span class="token punctuation">(</span>stmt<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h2 id="源码总结"><a href="#源码总结" class="header-anchor">#</a> 源码总结</h2> <p>总体上来说，MyBatis的源码还是比较简单的，只要大家踏下心来，花个两三天仔细研究下，基本上都能弄明白源码的主体脉络。为了方便小伙伴们理解，冰河为大家整理了一个MyBatis整体执行的流程图。</p> <p><img alt="" data-src="https://img-blog.csdnimg.cn/img_convert/441bbd4a972ac78b6f65b8a6db08d8b0.png" loading="lazy" class="lazy"></p> <p><strong>好了，今天就到这儿吧，我是冰河，我们下期见~~</strong></p> <h2 id="写在最后"><a href="#写在最后" class="header-anchor">#</a> 写在最后</h2> <blockquote><p>如果你觉得冰河写的还不错，请微信搜索并关注「 <strong>冰河技术</strong> 」微信公众号，跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术，「 <strong>冰河技术</strong> 」微信公众号更新了大量技术专题，每一篇技术文章干货满满！不少读者已经通过阅读「 <strong>冰河技术</strong> 」微信公众号文章，吊打面试官，成功跳槽到大厂；也有不少读者实现了技术上的飞跃，成为公司的技术骨干！如果你也想像他们一样提升自己的能力，实现技术能力的飞跃，进大厂，升职加薪，那就关注「 <strong>冰河技术</strong> 」微信公众号吧，每天更新超硬核技术干货，让你对如何提升技术能力不再迷茫！</p></blockquote> <p><img alt="" data-src="https://img-blog.csdnimg.cn/20200906013715889.png" loading="lazy" class="lazy"></p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/binghe001/BingheGuide/edit/master/docs/md/interview/2022-04-18-002-面试必问-聊聊MyBatis执行流程.md" target="_blank" rel="noopener noreferrer">在 GitHub 上编辑此页</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">上次更新: </span> <span class="time">2022/5/23</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/md/interview/2022-04-18-001-面试必问-聊聊JVM性能调优.html" class="prev">
          面试必问 | 聊聊JVM性能调优？
        </a></span> <span class="next"><a href="/md/interview/2022-05-06-面试必问-哪些场景下Spring的事务会失效.html">
          面试必问 | 哪些场景下Spring的事务会失效？
        </a>
        →
      </span></p></div> </main></div> <aside class="page-sidebar"> <div class="page-side-toolbar"><div class="option-box-toc-fixed"><div class="toc-container-sidebar"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="max-height:650px"><div style="font-weight:bold;text-align:center;">面试必问 | 聊聊MyBatis执行流程？</div> <hr> <div class="toc-box"><ul class="toc-sidebar-links"><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#mybatis源码解析" class="toc-sidebar-link">MyBatis源码解析</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#配置解析过程" class="toc-sidebar-link">配置解析过程</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#resources-getresourceasstream-resource-读取文件" class="toc-sidebar-link">Resources.getResourceAsStream(resource)读取文件</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#通过sqlsessionfactorybuilder创建sqlsessionfactory" class="toc-sidebar-link">通过SqlSessionFactoryBuilder创建SqlSessionFactory</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#sqlsessionfactory的创建" class="toc-sidebar-link">SqlSessionFactory的创建</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#sqlsession会话的创建过程" class="toc-sidebar-link">SqlSession会话的创建过程</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#创建transaction-两种方式" class="toc-sidebar-link">创建Transaction(两种方式)</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#创建executor" class="toc-sidebar-link">创建Executor</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#获得mapper对象" class="toc-sidebar-link">获得Mapper对象</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#执行sql" class="toc-sidebar-link">执行SQL</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用invoke代理方法" class="toc-sidebar-link">调用invoke代理方法</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用execute方法" class="toc-sidebar-link">调用execute方法</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用selectone其实是selectlist" class="toc-sidebar-link">调用selectOne其实是selectList</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#执行query方法" class="toc-sidebar-link">执行query方法</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#源码总结" class="toc-sidebar-link">源码总结</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#写在最后" class="toc-sidebar-link">写在最后</a><ul class="toc-sidebar-sub-headers"></ul></li></ul></div></div></div></div></div> <div class="option-box-toc-over"><img src="/images/system/toc.png" class="nozoom"> <span class="show-txt">目录</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="max-height:550px"><div style="font-weight:bold;text-align:center;">面试必问 | 聊聊MyBatis执行流程？</div> <hr> <div class="toc-box"><ul class="toc-sidebar-links"><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#mybatis源码解析" class="toc-sidebar-link">MyBatis源码解析</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#配置解析过程" class="toc-sidebar-link">配置解析过程</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#resources-getresourceasstream-resource-读取文件" class="toc-sidebar-link">Resources.getResourceAsStream(resource)读取文件</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#通过sqlsessionfactorybuilder创建sqlsessionfactory" class="toc-sidebar-link">通过SqlSessionFactoryBuilder创建SqlSessionFactory</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#sqlsessionfactory的创建" class="toc-sidebar-link">SqlSessionFactory的创建</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#sqlsession会话的创建过程" class="toc-sidebar-link">SqlSession会话的创建过程</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#创建transaction-两种方式" class="toc-sidebar-link">创建Transaction(两种方式)</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#创建executor" class="toc-sidebar-link">创建Executor</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#获得mapper对象" class="toc-sidebar-link">获得Mapper对象</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#执行sql" class="toc-sidebar-link">执行SQL</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用invoke代理方法" class="toc-sidebar-link">调用invoke代理方法</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用execute方法" class="toc-sidebar-link">调用execute方法</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#调用selectone其实是selectlist" class="toc-sidebar-link">调用selectOne其实是selectList</a></li><li class="toc-sidebar-sub-header"><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#执行query方法" class="toc-sidebar-link">执行query方法</a></li></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#源码总结" class="toc-sidebar-link">源码总结</a><ul class="toc-sidebar-sub-headers"></ul></li><li><a href="/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html#写在最后" class="toc-sidebar-link">写在最后</a><ul class="toc-sidebar-sub-headers"></ul></li></ul></div></div></div></div></div> <div class="option-box"><img src="/images/system/wechat.png" class="nozoom"> <span class="show-txt">手机看</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.9rem">微信扫一扫</span> <img height="180px" src="https://api.qrserver.com/v1/create-qr-code/?data=https://binghe001.github.io/md/interview/2022-04-18-002-%E9%9D%A2%E8%AF%95%E5%BF%85%E9%97%AE-%E8%81%8A%E8%81%8AMyBatis%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B.html" style="margin:10px;">
                可以<b>手机看</b>或分享至<b>朋友圈</b></div></div></div></div> <div class="option-box"><img src="/images/system/toggle.png" width="30px" class="nozoom"> <span class="show-txt">左栏</span></div> <div class="option-box"><img src="/images/system/xingqiu.png" width="25px" class="nozoom"> <span class="show-txt">星球</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.8rem;font-weight:bold;">实战项目<span style="font-size:8px;color:red;">「SpringCloud Alibaba实战项目」</span>、专属电子书、问题解答、简历指导、技术分享、晋升指导、视频课程</span> <img height="180px" src="/images/personal/xingqiu.png" style="margin:10px;"> <b>知识星球</b>：冰河技术
            </div></div></div></div> <div class="option-box"><img src="/images/system/wexin4.png" width="25px" class="nozoom"> <span class="show-txt">读者群</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.8rem;font-weight:bold;">添加冰河微信<span style="color:red;">(hacker_binghe)</span>进冰河技术学习交流圈「无任何套路」</span> <img src="/images/personal/hacker_binghe.jpg" height="180px" style="margin:10px;">
                PS：添加时请备注<b>读者加群</b>，谢谢！
              </div></div></div></div> <div class="option-box"><img src="/images/system/download-2.png" width="25px" class="nozoom"> <span class="show-txt">下资料</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.8rem;font-weight:bold;">扫描公众号，回复<span style="color:red;">“1024”</span>下载<span style="color:red;">100GB+</span>学习技术资料、PDF书籍、实战项目、简历模板等「无任何套路」</span> <img src="/images/personal/qrcode.png" height="180px" style="margin:10px;"> <b>公众号:</b> 冰河技术
              </div></div></div></div> <div class="option-box"><img src="/images/system/heart-1.png" width="25px" class="nozoom"> <span class="show-txt">赞赏我</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.8rem;font-weight:bold;">鼓励/支持/赞赏我</span> <img height="180px" src="/images/personal/encourage-head.png" style="margin:5px;"> <br>1. 不靠它生存但仍希望得到你的鼓励；
                <br>2. 时刻警醒自己保持技术人的初心；
              </div></div></div></div> <div title="面试必问 | 聊聊JVM性能调优？" class="option-box" style="padding-left:2px;text-align:center;"><a href="/md/interview/2022-04-18-001-面试必问-聊聊JVM性能调优.html"><img src="/images/system/pre2.png" width="30px" class="nozoom"> <span class="show-txt">上一篇</span></a></div> <div title="面试必问 | 哪些场景下Spring的事务会失效？" class="option-box" style="padding-left:2px;text-align:center;"><a href="/md/interview/2022-05-06-面试必问-哪些场景下Spring的事务会失效.html"><img src="/images/system/next2.png" width="30px" class="nozoom"> <span class="show-txt">下一篇</span></a></div></div>  <!----> </aside></div><div class="global-ui"><div class="read-more-wrap" style="display:none;position:absolute;bottom:0px;z-index:9999;width:100%;margin-top:-100px;font-family:PingFangSC-Regular, sans-serif;"><div id="read-more-mask" style="position: relative; height: 200px; background: -webkit-gradient(linear, 0 0%, 0 100%, from(rgba(255, 255, 255, 0)), to(rgb(255, 255, 255)));"></div> <a id="read-more-btn" target="_self" style="position: absolute; left: 50%; top: 70%; bottom: 30px; transform: translate(-50%, -50%); width: 160px; height: 36px; line-height: 36px; font-size: 15px; text-align: center; border: 1px solid rgb(222, 104, 109); color: rgb(222, 104, 109); background: rgb(255, 255, 255); cursor: pointer; border-radius: 6px;">阅读全文</a> <div id="btw-modal-wrap" style="display: none;"><div id="btw-mask" style="position: fixed; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.7; z-index: 999; background: rgb(0, 0, 0);"></div> <div id="btw-modal" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 300px; text-align: center; font-size: 13px; background: rgb(255, 255, 255); border-radius: 10px; z-index: 9999; font-family: PingFangSC-Regular, sans-serif;"><span id="btw-modal-close-btn" style="position: absolute; top: 5px; right: 15px; line-height: 34px; font-size: 34px; cursor: pointer; opacity: 0.2; z-index: 9999; color: rgb(0, 0, 0); background: none; border: none; outline: none;">×</span> <p id="btw-modal-header" style="margin-top: 40px; line-height: 1.8; font-size: 13px;">
                扫码或搜索：<span style="color: #E9405A; font-weight: bold;">冰河技术</span> <br>发送：<span id="fustack-token" class="token" style="color: #e9415a; font-weight: bold; font-size: 17px; margin-bottom: 45px;">290992</span> <br>即可<span style="color: #e9415a; font-weight: bold;">立即永久</span>解锁本站全部文章</p> <img src="/images/personal/qrcode.png" style="width: 180px; margin-top: 10px; margin-bottom: 30px; border: 8px solid rgb(230, 230, 230);"></div></div></div><div class="pay-read-more-wrap" style="display:none;position:absolute;bottom:0px;z-index:9999;width:100%;margin-top:-100px;font-family:PingFangSC-Regular, sans-serif;"><div id="pay-read-more-mask" style="position: relative; height: 200px; background: -webkit-gradient(linear, 0 0%, 0 100%, from(rgba(255, 255, 255, 0)), to(rgb(255, 255, 255)));"></div> <a id="pay-read-more-btn" target="_blank" style="position: absolute; left: 50%; top: 70%; bottom: 30px; transform: translate(-50%, -50%); width: 160px; height: 36px; line-height: 36px; font-size: 15px; text-align: center; border: 1px solid rgb(222, 104, 109); color: rgb(222, 104, 109); background: rgb(255, 255, 255); cursor: pointer; border-radius: 6px;">付费阅读</a></div></div></div>
    <script src="/assets/js/cg-styles.js?v=1653305936337" defer></script><script src="/assets/js/cg-4.js?v=1653305936337" defer></script><script src="/assets/js/cg-3.js?v=1653305936337" defer></script><script src="/assets/js/cg-276.js?v=1653305936337" defer></script><script src="/assets/js/cg-5.js?v=1653305936337" defer></script><script src="/assets/js/cg-6.js?v=1653305936337" defer></script><script src="/assets/js/cg-app.js?v=1653305936337" defer></script>
  </body>
</html>
